package com.example.tacocloud.controller;

import com.example.tacocloud.bean.Ingredient;
import com.example.tacocloud.bean.Ingredient.Type;
import com.example.tacocloud.bean.Order;
import com.example.tacocloud.bean.Taco;
import com.example.tacocloud.bean.User;
import com.example.tacocloud.dao.IngredientRepository;
import com.example.tacocloud.dao.TacoRepository;
import com.example.tacocloud.mapper.IngredientMapper;
import com.example.tacocloud.mapper.TacoMapper;
import com.example.tacocloud.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.security.Principal;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Controller
@RequestMapping("/design")
@SessionAttributes("order")
public class DesignTacoController {
    @Resource
    private IngredientMapper im;

    @Autowired
    private TacoMapper tm;

    @Autowired
    private UserMapper um;


    @ModelAttribute(name = "order")
    public Order order(){
        return new Order();
    }

//    @ModelAttribute(name = "taco")
//    public Taco taco(){
//        return new Taco();
//    }

    @ModelAttribute
    public void addIngredientsToModel(Model model) {
//        List<Ingredient> ingredients = Arrays.asList(
//                new Ingredient("FLTO", "Flour Tortilla", Type.WRAP),
//                new Ingredient("COTO", "Corn Tortilla", Type.WRAP),
//                new Ingredient("GRBF", "Ground Beef", Type.PROTEIN),
//                new Ingredient("CARN", "Carnitas", Type.PROTEIN),
//                new Ingredient("TMTO", "Diced Tomatoes", Type.VEGGIES),
//                new Ingredient("LETC", "Lettuce", Type.VEGGIES),
//                new Ingredient("CHED", "Cheddar", Type.CHEESE),
//                new Ingredient("JACK", "Monterrey Jack", Type.CHEESE),
//                new Ingredient("SLSA", "Salsa", Type.SAUCE),
//                new Ingredient("SRCR", "Sour Cream", Type.SAUCE)
//        );
//
//        Type[] types = Ingredient.Type.values();
//        for (Type type : types) {
//            model.addAttribute(type.toString().toLowerCase(),
//                    filterByType(ingredients, type));
//        }
        List<Ingredient> ingredients = new ArrayList<>(im.findAll());
        Type []types = Ingredient.Type.values();
        for (Type type:types){
            model.addAttribute(type.toString().toLowerCase(),
                    filterByType(ingredients,type));
        }
    }

    @GetMapping
    public String showDesignForm(Model model, Principal principal) {

        model.addAttribute("taco", new Taco());
        model.addAttribute("user", um.findByUsername(principal.getName()));
        return "design";
    }

    @PostMapping
    public String processDesign(@Valid @ModelAttribute("taco") Taco design, Errors errors,
                                @ModelAttribute Order order, Principal principal){
        if (errors.hasErrors()){
            log.error("Processing design: hasErrors " + errors.toString());
            return "design";
        }
        String tacoName = design.getName();
        Date createdAt = new Date();
        User user = um.findByUsername(principal.getName());
        tm.saveTacoInfo(tacoName, createdAt);
        long tacoId = tm.findTacoId(tacoName);
        for (Ingredient ingredient:design.getIngredients()){
            tm.saveIngredientToTaco(tacoId, ingredient.getId());
        }
        design.setCreatedAt(createdAt);
        design.setId(tacoId);
        order.setUid(user.getId());
        order.addDesign(design);
        log.error("processDesign :" + order.toString());
        return "redirect:/orders/current";
    }

    private List<Ingredient> filterByType(List<Ingredient> ingredients, Type type){
        return ingredients.stream()
                .filter(x -> x.getType().equals(type))
                .collect(Collectors.toList());
    }
}
